package login

import (
	"context"
	"fmt"
	"gitee.com/bobo-rs/creative-framework/pkg/utils"
	"gitee.com/bobo-rs/ecomp-analyzer-services/consts"
	"gitee.com/bobo-rs/ecomp-analyzer-services/enums"
	"gitee.com/bobo-rs/ecomp-analyzer-services/library/models"
	"gitee.com/bobo-rs/ecomp-analyzer-services/library/services/safety"
	"github.com/gogf/gf/v2/errors/gerror"
)

// ValidateBefore 验证账户登录设定规则-前置验证
func (l *sLogin) ValidateBefore(ctx context.Context, item models.LoginValidateBeforeItem) error {
	// 验证账户锁定
	err := l.validateAccountLock(ctx, item.Account)
	if err != nil {
		return err
	}
	return nil
}

// ValidateAfter 验证账户登录设定规则-后置验证
func (l *sLogin) ValidateAfter(ctx context.Context, item models.LoginValidateAfterItem) error {
	// 验证用户状态
	if item.Status != enums.UserStatusOk {
		return fmt.Errorf(`登录失败，账户%s`, item.Status.Fmt())
	}
	return nil
}

// ParseLoginParam 解析登录参数并验证规则
func (l *sLogin) ParseLoginParam(ctx context.Context, item models.LoginValidateBeforeItem) (parse *models.LoginParseParamItem, err error) {
	parse = &models.LoginParseParamItem{}
	// 解密签名
	parse.SignItem, err = safety.New().Verify(
		ctx, item.Sign, enums.SafeTagsLogin, item.IsRemove,
	)
	if err != nil {
		return nil, err
	}

	// 不同认证登录方式解析参数
	switch item.Oauth {
	case enums.UserOauthAccount:
		err = l.processAccountLoginParma(item, parse)
	default:
		// 手机号
		err = l.processMobileLoginParma(item, parse)
	}

	if err != nil {
		return nil, err
	}
	return parse, nil
}

// Decrypt 解密用户认证加密参数，例如：手机号、密码、账户等
func (l *sLogin) Decrypt(ciphertext, secret string) (string, error) {
	buff, err := safety.New().Decrypt(ciphertext, secret)
	if err != nil {
		return "", err
	}
	return string(buff), nil
}

// IncrAccountLockNum 叠加账户锁定次数
func (l *sLogin) IncrAccountLockNum(ctx context.Context, account string) (err error) {
	// 叠加MAC次数
	if err = l.SetLoginMacNum(ctx); err != nil {
		return err
	}
	// 叠加账户次数或手机号
	if len(account) > 0 {
		if err = l.SetLoginMacAccountNum(ctx, account); err != nil {
			return err
		}
	}
	return nil
}

// RemoveAccountLock 移除账号登录锁定规则
func (l *sLogin) RemoveAccountLock(ctx context.Context, account string) (err error) {
	// 移除MAC锁定
	err = l.RemoveLoginMac(ctx)
	// 移除Account
	err = l.RemoveLoginMacAccount(ctx, account)
	return err
}

// validateAccountLock 验证账户锁定规则
func (l *sLogin) validateAccountLock(ctx context.Context, account string) error {
	// 验证MAC锁定次数
	num, err := l.GetLoginMacNum(ctx)
	if err != nil {
		return err
	}
	// MAC次数
	if consts.LoginMacLockNum <= num {
		return fmt.Errorf(`登录失败%d次，锁定30分钟`, num)
	}

	// 验证账户
	if num, err = l.GetLoginMacAccountNum(ctx, account); err != nil {
		return err
	}
	if consts.LoginMacAccountLockNum <= num {
		return fmt.Errorf(`登录失败%d次, 账户锁定30分钟`, num)
	}
	return nil
}

// processAccountLoginParma 处理并验证账户登录参数
func (l *sLogin) processAccountLoginParma(in models.LoginValidateBeforeItem, parse *models.LoginParseParamItem) error {
	parse.Account = in.Account
	// 解密密码
	pwd, err := l.Decrypt(in.Pwd, parse.Secret)
	if err != nil {
		return err
	}
	parse.Pwd = pwd
	return nil
}

// processMobileLoginParma 处理并验证手机号登录参数
func (l *sLogin) processMobileLoginParma(in models.LoginValidateBeforeItem, parse *models.LoginParseParamItem) error {
	// 解密手机号
	mobile, err := l.Decrypt(in.Mobile, parse.Secret)
	if err != nil {
		return err
	}
	parse.Mobile = mobile
	parse.Account = mobile
	// 是否手机号
	if !utils.IsMobile(mobile) {
		return gerror.New(`手机号格式错误`)
	}
	return nil
}
